#include "instructions/references/get_static.hpp"
#include "rtda/frame.h"
#include "rtda/heap/cp_fieldref.h"
#include <stdexcept>

namespace jvm {
namespace instructions {

void GetStatic::Execute(Frame& frame) {
    auto cp = frame.GetMethod()->GetClass()->GetConstantPool();
    auto fieldRef = std::dynamic_pointer_cast<FieldRef>(cp->GetConstant(index_));
    auto field = fieldRef->ResolvedField();
    auto clazz = field->GetClass();
    // TODO: Initialize class

    if (!field->IsStatic()) {
        throw std::runtime_error("java.lang.IncompatibleClassChangeError");
    }

    auto descriptor = field->GetDescriptor();
    auto slotId = field->GetSlotId();
    auto slots = clazz->GetStaticVars();
    auto stack = frame.GetOperandStack();

    switch (descriptor[0]) {
        case 'Z': case 'B': case 'C': case 'S': case 'I':
            stack->PushInt(slots->GetInt(slotId));
            break;
        case 'F':
            stack->PushFloat(slots->GetFloat(slotId));
            break;
        case 'J':
            stack->PushLong(slots->GetLong(slotId));
            break;
        case 'D':
            stack->PushDouble(slots->GetDouble(slotId));
            break;
        case 'L': case '[':
            stack->PushRef(slots->GetRef(slotId));
            break;
        default:
            // TODO: Handle other cases
            break;
    }
}

} // namespace instructions
} // namespace jvm